package com.wangjiangwen.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wangjiangwen.bean.user.CaptchaVO;
import com.wangjiangwen.bean.user.ChangePasswordDTO;
import com.wangjiangwen.bean.user.LoginDTO;
import com.wangjiangwen.bean.user.UserVO;
import com.wangjiangwen.constant.RedisKey;
import com.wangjiangwen.entity.User;
import com.wangjiangwen.exceptions.WjwException;
import com.wangjiangwen.mapper.UserMapper;
import com.wangjiangwen.service.UserService;
import com.wangjiangwen.util.DigestUtil;
import com.wangjiangwen.util.IdUtil;
import com.wangjiangwen.util.ObjUtil;
import com.wf.captcha.SpecCaptcha;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author gavin
 * @since 2024-07-01
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    UserMapper userMapper;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public CaptchaVO getCaptCha(String type) {
        SpecCaptcha captcha = new SpecCaptcha();
        captcha.setLen(4);
        String text = captcha.text().toLowerCase();
        String key = IdUtil.simpleUUID();
        String code = "";
        if ("login".equals(type)) {
            code = RedisKey.LOGIN_CODE;
        } else if ("register".equals(type)) {
            code = RedisKey.REGISTER_CODE;
        }
        stringRedisTemplate.opsForValue().set(code + key, text, Duration.ofSeconds(60));
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setImage(captcha.toBase64());
        captchaVO.setKey(key);
        return captchaVO;
    }

    @Override
    public SaTokenInfo login(LoginDTO loginDTO) {
        String realCode = stringRedisTemplate.opsForValue().get(RedisKey.LOGIN_CODE + loginDTO.getKey());
        if (!Objects.equals(realCode, loginDTO.getCode())) {
            throw new RuntimeException("验证码错误");
        }
        String account = loginDTO.getAccount();
        String password = loginDTO.getPassword();
        LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery().eq(User::getAccount, account);
        User user = getOne(wrapper);
        if (Objects.isNull(user)) {
            throw new RuntimeException("账号不存在");
        }
        if (DigestUtil.unMatched(password, user.getSalt(), user.getPassword())) {
            throw new RuntimeException("密码错误");
        }
        StpUtil.login(user.getId());
        return StpUtil.getTokenInfo();
    }

    @Override
    public void logout() {
        if (StpUtil.isLogin()) {
            StpUtil.logout();
        }
    }

    @Override
    public UserVO getInfo() {
        return ObjUtil.copy(getById(StpUtil.getLoginIdAsLong()), UserVO.class);
    }

    @Override
    public void changePassword(ChangePasswordDTO changePasswordDTO) {
        User user = getById(StpUtil.getLoginIdAsLong());
        String originPassword = user.getPassword();
        String salt = user.getSalt();
        String oldPassword = changePasswordDTO.getOldPassword();
        if (DigestUtil.unMatched(oldPassword, salt, originPassword)) {
            throw new WjwException("旧密码不正确!");
        }
        String password = DigestUtil.encrypt(changePasswordDTO.getNewPassword(), salt);
        user.setPassword(password);
        updateById(user);
    }
}
